Shiny.addCustomMessageHandler("scatterplot_values", function(message) {

    var dataset = message[0];
    var info = message[1];

    // for dropdown
    var filters = ["regiao", "uf", "mesorregiao", "microrregiao",
		   "ds_grupo_agcausadores", "cnae_secao", "ds_natureza_lesao",
		   "cbo_grande_grupo", "agrupamento_parte_do_corpo",
		   "ds_tipo_acidente", "ds_tipo_local_acidente", "turno"];

    var current_grouping = "regiao";

    var margin = {top: 20, right: 50, bottom: 20, left: 50},
        width = (window.innerWidth * 0.8) - margin.right - margin.left,
        height =  (window.innerHeight * 0.8) - margin.top - margin.bottom;

    // Create the scatterplot canvas
    var scatterplot = d3.select("#scatterplot_area")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
	.append("g")
	.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var xScale = d3.scaleLinear()
        .domain(d3.extent(dataset, function(d) { return d[0]; }))
        .range([0, width]);

    var yScale = d3.scaleLinear()
        .domain(d3.extent(dataset, function(d) { return d[1]; }))
        .range([height, 0]);

    /*var colorScale = d3.scaleSequential()
	.domain(info[current_grouping].filter(onlyUnique))
	.interpolator(d3.interpolateRainbow);*/

    var colorScale = d3.scaleOrdinal()
	.domain(info[current_grouping].filter(onlyUnique))
	.range(d3.range(info[current_grouping].filter(onlyUnique).length)
	       .map(d3.scaleSequential()
		    .domain([0, info[current_grouping].filter(onlyUnique).length])
		    .interpolator(d3.interpolateRainbow)));

    var saved_selections = [];

    var brush = d3.polybrush()
    //Polybrush goes against convention and ignores the previous translation?
        .x(d3.scaleLinear().range([-margin.left, width]))
        .y(d3.scaleLinear().range([height, -margin.top]))
        .on("start", function() {
    	    scatterplot.selectAll(".selected").classed("selected", false);
	    tooltip.style("visibility", "hidden");
        })
        .on("brush", highlightBrushedPoints)
        .on("end", displayTable);
    scatterplot.append("g")
        .attr("class", "brush")
        .call(brush);

    // functions
    function clearTableRows() {

        hideTableColNames();
        d3.selectAll(".row_data").remove();
    }

    function hideTableColNames() {
        d3.select("table").style("visibility", "hidden");
    }

    function showTableColNames() {
        d3.select("table").style("visibility", "visible");
    }

    function highlightBrushedPoints() {

        scatterplot.selectAll(".point").classed("selected", function(d) {
            //get the associated circle
            //var id = d3.select(this).attr("id");
            //var i = id.substr(id.indexOf("-") + 1, id.length);

            if (brush.isWithinExtent(xScale(d[0]), yScale(d[1]))) {
                return true;
            } else {
                return false;
            }
        });
    }

    function displayTable() {

        //var d_brushed =  d3.selectAll(".point.selected").data();

	/*
        // populate table if one or more elements is brushed
        if (d_brushed.length > 0) {
    	    clearTableRows();
    	    d_brushed.forEach(d_row => populateTableRow(d_row));
        } else {
    	    clearTableRows();
            }*/

	// Save and unsave selections
	// Still don get why this only works with body
	d3.select("body").on("keydown", function() {
	    var key = d3.event.key;

	    switch(key) {
	    case "s":
		save_selection();
		break;
	    case "c":
		unsave_selection();
		break;
	    default:
		break;
	    }

	});

    }

    function populateTableRow(d_row) {

        showTableColNames();

        var d_row_filter = [d_row[0]];
	console.log(d_row);

        d3.select("table")
            .append("tr")
            .attr("class", "row_data")
            .selectAll("td")
            .data(d_row_filter)
            .enter()
            .append("td")
            .attr("align", (d, i) => i == 0 ? "left" : "right")
            .text(d => d);
    }

    var points = scatterplot.append("g").attr("id", "points");

    // Criar círculos
    points.selectAll("circle")
        .data(dataset)
	.enter()
	.append("circle")
	.attr("class", "point")
        .attr("id", function(d, i) {
    	    //return "point-" + i;
	    return i;
        })
        .attr("r", 3)
        .attr("cx", function(d) {
    	    return xScale(d[0]);
        })
        .attr("cy", function(d) {
    	    return yScale(d[1]);
        })
	.style("fill", function(d, i) {
	    return colorScale(info[current_grouping][i]);
	})
	.on("mouseover", function(d) {
	    var id = d3.select(this).attr('id');
	    if(d3.select(this).attr('class') == "point saved") {
		t_text = "";
		d3.selectAll(".saved").each(function() {
		    id = d3.select(this).attr('id');
		    t_text += info.municipio[id] + ", " + info.uf[id] + "<br/>";
		});
	    } else {
		t_text = info.municipio[id] + ", " + info.uf[id];
	    }

	    tooltip.html(t_text);
	    return tooltip.style("visibility", "visible");
	})
	.on("mouseout", function(d) {
	    return tooltip.style("visibility", "hidden");
	})
	.on("mousemove", function() {
	    return tooltip.style("top", (d3.event.pageY-10) + "px").style("left", (d3.event.pageX+10) + "px");
	});

    // Save a selection
    function save_selection() {
	s = d3.selectAll(".point.selected");

	s.classed("saved", true);

	saved_selections.push(s);
    }

    // this might be used in the future
    /*function unsave_selection(i) {
	s = saved_selections.splice(i, 1);
	s.classed("saved", false);
    }*/

    // temporary
    function unsave_selection() {
	saved_selections = [];
	d3.selectAll(".point.saved")
	    .classed("saved", false);
    }

    // Update circle colors based on grouping
    function updateColors() {
	points.selectAll("circle")
	    .style("fill", function(d,i) {
		return colorScale(info[current_grouping][i]);
	    });
    }

    // Select or deselect a group colouring
    function toggleGroupColor() {
	var selectValue = d3.select('select').property('value');

	points.selectAll("circle")
	    .filter(function(d, i) {
		return info[current_grouping][i] == selectValue;
	    })
	    .style("fill", function(d, i) {
		    
		if(d3.select(this).style('fill') == "black") {
		    return colorScale(selectValue);
		} else {
		    return "black";
		}
	    });
    }

    function toggleAllColors() {
	cb = d3.select(this);

	if(cb.property("checked")) {
	    d3.selectAll('.checkbox').property('checked', true);
	    points.selectAll("circle")
	    	.style("fill", function(d, i) {
		    return colorScale(info[current_grouping][i]);
		});
	} else {
	    d3.selectAll('.checkbox').property('checked', false);
	    points.selectAll("circle")
	    	.style("fill", "black");
	}

    }

    // Create a dropdown menu
    var select = d3.select("#sct_dropdown_area")
	.append('select')
  	.attr('class', 'filters_select')
	.on('change', onchange);

    var options = select
	.selectAll('option')
	.data(filters)
	.enter()
	.append('option')
	.text(function (d) { return d; });

    function onchange() {
	var selectValue = d3.select('.filters_select')
	    .property('value');

	for(var i = 0; i < filters.length; i++) {
	    if(selectValue == filters[i]) {
		current_grouping = selectValue;
		colorScale.domain(info[current_grouping].filter(onlyUnique))
		    .range(d3.range(info[current_grouping].filter(onlyUnique).length)
			   .map(d3.scaleSequential()
				.domain([0, info[current_grouping].filter(onlyUnique).length])
				.interpolator(d3.interpolateRainbow)));
	    }
	}

	updateColors();
	create_categories_menu();
    };

    // Create a menu to select grouping categories
    function create_categories_menu() {
	var categories = info[current_grouping].filter(onlyUnique);

	categories.sort();

	d3.select('.categories_select').remove();

	var select = d3.select("#sct_checkbox_area")
	    .append('div')
	    .attr('class', 'categories_select')
	    .append('select')
	    .on('change', 0);//on change does nothing, except enable to click on options

	var options = select
	    .selectAll('option')
	    .data(categories)
	    .enter()
	    .append('option').attr("class", "non-picked")
	    .text(function (d) { return d; })
	    .on("click", function(d){
		if(d3.select(this).attr("class") == "picked") {
		    d3.select(this).attr("class", "non-picked");
		    toggleGroupColor();// Allows recolouring the points without selection of other categorie.
		} else {
		    d3.select(this).attr("class", "picked");
		    toggleGroupColor();

		}
	    });
    }

    // Create a toggle all checkbox
    var all_box = d3.select("#sct_checkboxall_area")
	.append("div")
	.attr("class", "checkbox");

    all_box.append("input")
	.attr("type", "checkbox")
	.attr("checked", "true")
	.attr("id", "cb_all")
	.on("change", toggleAllColors);

    all_box.append("label")
	.attr("for", "cb_all")
	.text("tudo");

    create_categories_menu();

    // filter function to get only unique values in array
    function onlyUnique(value, index, self) {
	return self.indexOf(value) === index;
    }

    // tooltip code

    var tooltip = d3.select("body")
	.append("div")
	.style("position", "absolute")
	.style("z-index", "10")
	.style("visibility", "hidden")
	.style("opacity", 1)
	.style("color", "white")
	.style("padding", "8px")
	.style("background-color", "rgba(0, 0, 0, 0.75)")
	.style("border-radius", "6px")
	.style("font", "12px sans-serif")
	.text("tooltip");

    var t_text = "";
});
